package com.reyco1.medusa.data.binding
{
	import com.reyco1.medusa.core.IDisposable;
	import com.reyco1.medusa.events.DataEvent;
	
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;

	public dynamic class BindableObject extends BindableCore implements IDisposable, IEventDispatcher
	{
		private var bindings:Dictionary;
		
		public function BindableObject()
		{
			super();
			bindings = new Dictionary(true);
		}
		
		override public function clear():void
		{
			bindings = null;
		}
		
		public function bind(property:String, target:Object, setterOrFunction:* = null):void
		{
			if(bindings[target] == undefined) 
				bindings[target] = new Dictionary();
			if(bindings[target][property] != undefined)
				log("property \"" + property + "\" already bound.", "warning");
			else
				bindings[target][property] = {target:target, setterOrFunction:setterOrFunction, isFunction:setterOrFunction is Function ? true : false};
		}
		
		public function unbind(target:Object, property:String = null):void
		{
			if(property != null)
			{
				delete bindings[target][property];
			}else
			{
				bindings[target] = null;
				delete bindings[target];
			}
		}
		
		override public function handlePropertyChange(object:Object):void
		{
			for each(var propertyDictionary:Dictionary in bindings)
			{
				if(propertyDictionary[object.property] != undefined)
				{
					if(propertyDictionary[object.property].isFunction)
					{
						(propertyDictionary[object.property].setterOrFunction as Function).apply(propertyDictionary[object.property].target, [object]);
					}
					else
					{
						try
						{
							propertyDictionary[object.property].target[propertyDictionary[object.property].setterOrFunction] = object.newValue;
						}
						catch(e:ReferenceError)
						{
							propertyDictionary[object.property].target[object.property] = object.newValue;
						}
						
					}					
					dispatchEvent(new DataEvent(DataEvent.PROPERTY_CHANGED, object));
				}
			}
		}
	}
}